#pragma once

#include "AbstractTableView.h"

class AbstractStdTable : public AbstractTableView {
  Q_OBJECT
 public:
  explicit AbstractStdTable(QWidget* parent = 0);
  QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col,
                       int x, int y, int w, int h) override;
  void updateColors() override;
  void reloadData() override;

  void mouseMoveEvent(QMouseEvent* event) override;
  void mousePressEvent(QMouseEvent* event) override;
  void mouseDoubleClickEvent(QMouseEvent* event) override;
  void mouseReleaseEvent(QMouseEvent* event) override;
  void keyPressEvent(QKeyEvent* event) override;

  void enableMultiSelection(bool enabled);
  void enableColumnSorting(bool enabled);

  // Selection Management
  void expandSelectionUpTo(int to);
  void expandUp();
  void expandDown();
  void expandTop();
  void expandBottom();
  void setSingleSelection(int index);
  int getInitialSelection() const;
  QList<int> getSelection() const;
  void selectStart();
  void selectEnd();
  void selectNext();
  void selectPrevious();
  void selectAll();
  bool isSelected(int base, int offset) const;
  bool scrollSelect(int offset);

  // Data Management
  void addColumnAt(int width, QString title, bool isClickable,
                   QString copyTitle = "");
  void deleteAllColumns() override;

  virtual QString getCellContent(int r, int c) = 0;
  virtual bool isValidIndex(int r, int c) = 0;
  virtual void sortRows(int column, bool ascending) = 0;
  duint getDisassemblyPopupAddress(int mousex, int mousey) override;

  // context menu helpers
  void setupCopyMenu(QMenu* copyMenu);
  void setupCopyColumnMenu(QMenu* copyMenu);
  void setupCopyMenu(MenuBuilder* copyMenu);
  void setupCopyColumnMenu(MenuBuilder* copyMenu);
  void setCopyMenuOnly(bool bSet, bool bDebugOnly = true);

  // draw helpers
  void setHighlightText(QString highlightText, int minCol = 0) {
    mHighlightText = highlightText;
    mMinimumHighlightColumn = minCol;
  }

  void setAddressColumn(int col, bool cipBase = false) {
    mAddressColumn = col;
    bCipBase = cipBase;
  }

  void setAddressLabel(bool addressLabel) { bAddressLabel = addressLabel; }

  bool setDisassemblyPopupEnabled(bool enabled) {
    return bDisassemblyPopupEnabled = enabled;
  }

 signals:
  void selectionChangedSignal(int index);
  void keyPressedSignal(QKeyEvent* event);
  void doubleClickedSignal();
  void contextMenuSignal(const QPoint& pos);

 public slots:
  void copyLineSlot();
  void copyTableSlot();
  void copyTableResizeSlot();
  void copyLineToLogSlot();
  void copyTableToLogSlot();
  void copyTableResizeToLogSlot();
  void copyEntrySlot();
  void exportTableSlot();
  void contextMenuRequestedSlot(const QPoint& pos);
  void headerButtonPressedSlot(int col);

 protected:
  QString copyTable(const std::vector<int>& colWidths);

  struct SelectionData {
    int firstSelectedIndex = 0;
    int fromIndex = 0;
    int toIndex = 0;
  };

  SelectionData mSelection;

  enum { NoState, MultiRowsSelectionState } mGuiState = NoState;

  bool mIsMultiSelectionAllowed = false;
  bool mCopyMenuOnly = false;
  bool mCopyMenuDebugOnly = true;
  bool mIsColumnSortingAllowed = true;

  std::vector<QString> mCopyTitles;

  struct SortData {
    int column = -1;
    bool ascending = true;
  } mSort;

  QColor mCipBackgroundColor;
  QColor mCipColor;
  QColor mBreakpointBackgroundColor;
  QColor mBreakpointColor;
  QColor mHardwareBreakpointBackgroundColor;
  QColor mHardwareBreakpointColor;
  QColor mBookmarkBackgroundColor;
  QColor mBookmarkColor;
  QColor mLabelColor;
  QColor mLabelBackgroundColor;
  QColor mSelectedAddressBackgroundColor;
  QColor mSelectedAddressColor;
  QColor mAddressBackgroundColor;
  QColor mAddressColor;
  QColor mTracedBackgroundColor;
  QColor mTracedSelectedAddressBackgroundColor;
  bool bCipBase = false;
  QString mHighlightText;
  int mMinimumHighlightColumn = 0;
  int mAddressColumn = -1;
  bool bAddressLabel = true;
  bool bDisassemblyPopupEnabled = true;

  QAction* mCopyLine;
  QAction* mCopyTable;
  QAction* mCopyTableResize;
  QAction* mCopyLineToLog;
  QAction* mCopyTableToLog;
  QAction* mCopyTableResizeToLog;
  QAction* mExportTableCSV;
};
